<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <!-- 
      4.Vue3.0中的响应式原理
      
      Vue3.0的响应式

        1.实现原理:

          a.通过Proxy(代理): 拦截对象中任意属性的变化, 包括: 属性值的读写,属性的添加,属性的删除等

          b.通过Reflect(反射): 对被代理对象(源对象)的属性进行操作

          c.MDN文档中描述的Proxy与Reflect:

            Proxy: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

            Reflect: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

            new Proxy(data, {
                //拦截读取属性值
                get (target, prop) {
                    return Reflect.get(target, prop)
                }
                //拦截设置属性值或添加新属性
                set (target, prop, value) {
                    return Reflect.set(target, prop, value)
                }
                // 拦截删除属性
                deleteProperty (target, prop) {
                    return Reflect.deleteProperty(target, prop)
                }
            })

            prop.name = 'tom'

   -->
    <script>
        let person = {
            name: '张三',
            age: 18
        }

        // 模拟Vue2中实现响应式
        let p = {}
        // 第一个参数,给哪个对象追加属性
        Object.defineProperty(p, 'name', {
            get () {
                return person.name
            },
            set (value) {
                console.log('有人修改了name属性,我发现了,我要去更新界面')
                person.name = value
            }
        })
        Object.defineProperty(p, 'age', {
            configurable: true, //可配置的，加了之后可以删除属性,
            get () {
                return person.age
            },
            set (value) {
                console.log('有人修改了age属性,我发现了,我要去更新界面')
                person.age = value
            }
        })
        // 无论是添加或删除属性都捕获不到



        // 模拟Vue3中实现响应式
        // Proxy代理对象
        // Reflect反射对象
        const v = new Proxy(person, {
            // 有人读取v的某个属性时调用
            get (target, propName) {
                console.log('有人读取了v身上的某个属性')
                console.log(target,propName) // target源数据, propName读取的属性的名
                console.log(`有人读取了v身上的${propName}属性`)
                // return target[propName]
                return Reflect.get(target,propName)
            },
            // 有人修改v的某个属性或给v增加属性时调用
            set (target, propName, value) {
                console.log(`有人修改了v身上的${propName}属性, 我要去更新界面了`)
                // target[propName] = value
                Reflect.set(target, propName, value)
            },
            // 有人删除v的某个属性时调用
            deleteProperty (target, propName) {
                console.log(`有人删除了v身上的${propName}属性, 我要去更新界面了`)
                // return delete target[propName]
                return Reflect.deleteProperty(target, propName)
            }
        })


        let obj = {a:1, b:2}
        // Object.defineProperty(obj,'c',{
        //     get () {
        //         return 3
        //     }
        // })
        // Object.defineProperty(obj,'c',{
        //     get () {
        //         return 4
        //     }
        // })
        // 会报错程序无法执行
        try {
            Object.defineProperty(obj,'c',{
                get () {
                    return 3
                }
            })
            Object.defineProperty(obj,'c',{
                get () {
                    return 4
                }
            })
        }catch (error) {
            console.log(error)
        }
        //通过Reflect(反射对象)
        const x1 = Reflect.defineProperty(obj,'c',{
            get () {
                return 3
            }
        })
        console.log(x1)
        const x2 = Reflect.defineProperty(obj,'c',{
            get () {
                return 4
            }
        })
        console.log(x2)
        if(x2) {
            console.log('某某某操作成功了!')
        } else {
            console.log('某某某操作失败了!')
        }
        console.log('@@@@@@')
    </script>
</body>
</html>